package com.duguo.dynamicmvc.factory.processor.model;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javassist.CtClass;
import javassist.CtMethod;
import javassist.bytecode.annotation.AnnotationImpl;

import com.duguo.dynamicmvc.factory.utils.BeanUtils;
import com.duguo.dynamicmvc.factory.utils.javassist.MethodUtils;
import com.duguo.dynamicmvc.model.annotation.DefaultValue;
import com.duguo.dynamicmvc.model.annotation.Parameter;
import com.duguo.dynamicmvc.model.annotation.Validator;

public class ModelAnnotationReaderImpl implements ModelAnnotationReader{


	public String getDefaultValue(CtClass modelImplCtClass,String fieldName,CtClass fieldType,boolean isGetter)throws Exception {
		String accessorName;
		if(isGetter){
			accessorName=BeanUtils.getGetterName(fieldName, fieldType==CtClass.booleanType);
		}else{
			accessorName=BeanUtils.getSetterName(fieldName);			
		}
		List<CtMethod> getterCtMethods=MethodUtils.findMethodsFromAllInterfaces(modelImplCtClass, accessorName);
		for(CtMethod getterCtMethod:getterCtMethods){
			for(Object obj:getterCtMethod.getAnnotations()){
				if(obj instanceof DefaultValue){
					DefaultValue defaultValue= (DefaultValue)obj;
					return defaultValue.value();
				}
			}
		}
		return null;
	}
	



	public String getParameterName(CtClass modelImplCtClass,String fieldName,CtClass fieldType)throws Exception {
		Parameter parameter=getParameter(modelImplCtClass,fieldName,fieldType);
		if(parameter!=null && parameter.name()!=null && parameter.name().length()>0)
			return parameter.name();
		return null;
	}


	public boolean isParameter(CtClass modelImplCtClass,String fieldName,CtClass fieldType) throws Exception{
		Parameter parameter=getParameter(modelImplCtClass,fieldName,fieldType);
		return parameter!=null;
	}
	

	public List getValidators(CtClass modelImplCtClass, String fieldName, CtClass fieldType)throws Exception {
		List<Object> validators=new ArrayList<Object>();
		Set<String> collectedValidators=new HashSet<String>();
		String getterName=BeanUtils.getGetterName(fieldName, fieldType==CtClass.booleanType);
		List<CtMethod> getterCtMethods=MethodUtils.findMethodsFromAllInterfaces(modelImplCtClass, getterName);
		for(CtMethod getterCtMethod:getterCtMethods){
			for(Object obj:getterCtMethod.getAnnotations()){
				AnnotationImpl annotationImpl=(AnnotationImpl)Proxy.getInvocationHandler(obj);
				if(annotationImpl.getAnnotation().getTypeName().indexOf("."+Validator.class.getSimpleName()+"$")>0 && !collectedValidators.contains(annotationImpl.getTypeName())){
					collectedValidators.add(annotationImpl.getTypeName());
					validators.add(annotationImpl);
				}
			}
		}
		return validators;
	}



	

	public Parameter getParameter(CtClass modelImplCtClass,String fieldName,CtClass fieldType) throws Exception{
		String getterName=BeanUtils.getGetterName(fieldName, fieldType==CtClass.booleanType);
		List<CtMethod> getterCtMethods=MethodUtils.findMethodsFromAllInterfaces(modelImplCtClass, getterName);
		for(CtMethod getterCtMethod:getterCtMethods){
			for(Object obj:getterCtMethod.getAnnotations()){
				if(obj instanceof Parameter){
					return (Parameter)obj;
				}
			}
		}
		return null;
	}
	
	

	public List<Object> getNoneRequiredValidators(List validators) {
		List<Object> noneRequiredValidators=new ArrayList<Object>();
		for(Object obj:validators){
			if(((AnnotationImpl)obj).getAnnotation().getTypeName().indexOf("."+Validator.class.getSimpleName()+"$Required")<0){
				noneRequiredValidators.add(obj);
			}
		}
		return noneRequiredValidators;
	}
	
	public AnnotationImpl getRequiredValidator(List validators) {
		for(Object obj:validators){
			if(((AnnotationImpl)obj).getAnnotation().getTypeName().indexOf("."+Validator.class.getSimpleName()+"$Required")>0)
				return (AnnotationImpl)obj;
		}
		return null;
	}

	public String getValidatorName(AnnotationImpl annotationImpl)throws Exception  {
		String annotationName=annotationImpl.getAnnotation().getTypeName();
		String validatorName=annotationName.substring(annotationName.indexOf("$")+1,annotationName.indexOf("$")+2).toLowerCase();
		validatorName+=annotationName.substring(annotationName.indexOf("$")+2).toLowerCase();
		return validatorName;
	}
}
